package com.zimmur.app.mocolink.background.util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.FileImageOutputStream;

import org.im4java.core.ConvertCmd;
import org.im4java.core.IMOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zimmur.app.mocolink.background.common.PropertiesCommon;



public class ImageMagick {
	private static final Logger log = LoggerFactory.getLogger(ImageMagick.class);
	private static Object syncObj=new Object();
	/*	 1、指定宽，高自适应，等比例缩放;	 
	2、指定高， 宽自适应，等比例缩放;	 
	3、指定最长边，短边自适应，等比例缩放;	 
	4、指定最短边，长边自适应，等比例缩放;	 
	5、指定最大宽高， 等比例缩放;	 
	6、固定宽高， 居中裁剪）	 
	*/	
	public static int DefineWidth=1; 	
	public static int DefineHeight=2; 	
	public static int DefineLong=3; 	
	public static int DefineShort=4; 	
	public static int MaxWidthHeight=5; 	
	public static int DefineWidthHeight=6; 	
	/** * ImageMagick的路径 */
	public static String gmPath = null;
	static { /** 获取ImageMagick的路径 */
		// Properties prop = new PropertiesFile().getPropertiesFile();
		// linux下不要设置此值，不然会报错
		// imageMagickPath = prop.getProperty("imageMagickPath");
		gmPath = PropertiesCommon.getProperty("gm.path");
		if(gmPath != null){
			ConvertCmd.setGlobalSearchPath(gmPath);
		}
	}

	// 指定最大宽高， 等比例缩放;
	private IMOperation resizeMaxWidthHeight(String src, String desc, int width, int height,String quality) {
		IMOperation op = new IMOperation();
		if ((quality != null && !quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage(src);
		op.resize(width, height, '!');
		op.addImage(desc);
		return op;
	}

	// 固定宽高， 居中裁剪
	private IMOperation resizeDefineWidthHeight(String src, String desc, int width, int height,String quality) {
		IMOperation op = new IMOperation();
		if ((quality != null && !quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage(src);
		op.gravity("center").extent(width, height);
		op.addImage(desc);
		return op;
	}

	private ConvertCmd getCmd() {
		ConvertCmd cmd = new ConvertCmd(true);
		return cmd;
	}

	// 指定最长边，短边自适应，等比例缩放;
	private IMOperation resizeDefineLong(String src, String desc, int maxFrame,String quality) throws Exception {
		InputStream is = new FileInputStream(src);
		// 通过文件名称读取 
		BufferedImage buff = ImageIO.read(is);
		int srcWidth = buff.getWidth();// 得到图片的宽度
		int srcHeight = buff.getHeight();// 得到图片的高度
		is.close(); // 关闭Stream
		IMOperation op = new IMOperation();
		if ((quality != null && !quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage(src);
		if (srcWidth > srcHeight) {
			op.resize(maxFrame, null);
		} else {
			op.resize(null, maxFrame);
		}
		op.addImage(desc);
		return op;
	}

	// 指定最短边，长边自适应，等比例缩放;
	private IMOperation resizeDefineShort(String src, String desc, int minFrame,String quality) throws Exception {
		InputStream is = new FileInputStream(src);
		// 通过文件名称读取
		BufferedImage buff = ImageIO.read(is);
		int srcWidth = buff.getWidth();// 得到图片的宽度
		int srcHeight = buff.getHeight();// 得到图片的高度
		is.close(); // 关闭Stream
		IMOperation op = new IMOperation();
		if ((quality != null && !quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage(src);
		if (srcWidth < srcHeight) {
			op.resize(minFrame, null);
		} else {
			op.resize(null, minFrame);
		}
		op.addImage(desc);
		return op;
	}
	//指定宽，高自适应，等比例缩放;	
	public IMOperation resizeDefineWidth(String src,String desc, int width, int height,String quality){		
		IMOperation op = new IMOperation();	
		if ((quality != null && !quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage(src);		
		op.resize(width,null);		
		op.addImage(desc);				
		return op;	
	}		
	//指定高， 宽自适应，等比例缩放;	
	public IMOperation resizeDefineHeight(String src,String desc, int width, int height,String quality){		
		IMOperation op = new IMOperation();		
		
		if ((quality != null && !quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage(src);		
		op.resize(null,height);		
		op.addImage(desc);				
		return op;	
	}
	/**	 
	 * * 图片缩放的方法	 
	* 	 
	* @param mode 1、指定宽，高自适应，等比例缩放;2、指定高， 宽自适应，等比例缩放;3、指定最长边，短边自适应，等比例缩放; 
	* 4、指定最短边，长边自适应，等比例缩放; 5、指定最大宽高， 等比例缩放;	 6、固定宽高， 居中裁剪）	 
	* @param src 源文件路径	 
	* @param desc 目标文件路径	 
	* @param width 指定宽	 
	* @param height 指定高	 
	* @param maxFrame 指定最长边	 
	* @param minFrame 指定最短边	 
	* @return	 
	* @throws Exception	 
	*/	
	public String resize(int mode, String src, String desc,String dest, int width, int height, int maxFrame, int minFrame,String quality)
			throws Exception {
		String str = "";
		// create command
		ConvertCmd cmd = getCmd();
		IMOperation op = null;
		if (mode == ImageMagick.DefineWidth) {
			op = this.resizeDefineWidth(src, desc, width, height,quality);
		} else if (mode == ImageMagick.DefineHeight) {
			op = this.resizeDefineHeight(src, desc, width, height,quality);
		} else if (mode == ImageMagick.DefineLong) {
			op = this.resizeDefineLong(src, desc, maxFrame,quality);
		} else if (mode == ImageMagick.DefineShort) {
			op = this.resizeDefineShort(src, desc, minFrame,quality);
		} else if (mode == ImageMagick.MaxWidthHeight) {
			op = this.resizeMaxWidthHeight(src, desc, width, height,quality);
		} else if (mode == ImageMagick.DefineWidthHeight) {
			op = this.resizeDefineWidthHeight(src, desc, width, height,quality);
		}
		
		cmd.run(op);
		checkImageSize(mode,desc,dest,width,height,quality);
		return dest;
	}
	//检查处理后图片,按比例中心点裁剪
	private void checkImageSize(int mode,String desc,String dest,int width, int height,String quality)throws Exception{
		File file = new File(desc);
		if(width>0 && height>0){			
			if(file.exists()){
				InputStream is = new FileInputStream(desc);
				// 通过文件名称读取
				BufferedImage buff = ImageIO.read(is);
				int srcWidth = buff.getWidth();// 得到图片的宽度
				int srcHeight = buff.getHeight();// 得到图片的高度
				is.close(); // 关闭Stream
				
				if(srcWidth>width || srcHeight>height){
					ConvertCmd cmd = getCmd();
					IMOperation op = null;
					op = this.resizeDefineWidthHeight(desc, dest, width, height,"");
					cmd.run(op);
					file.delete();
				}else{
					File destFile = new File(dest);
					if(!destFile.exists()){
						file.renameTo(destFile);
					}
				}	
			}
			
		}else{
			File destFile = new File(dest);
			if(!destFile.exists()){
				file.renameTo(destFile);
			}
			file.delete();
		}
	}

	/**
	 * * 根据坐标裁剪图片
	 * 
	 * @param srcPath
	 *            要裁剪图片的路径
	 * @param newPath
	 *            裁剪图片后的路径
	 * @param x
	 *            起始横坐标
	 * @param y
	 *            起始挫坐标
	 * @param x1
	 *            结束横坐标
	 * @param y1
	 *            结束挫坐标
	 */
	public static void cutImage(String srcPath, String newPath, int x, int y, int x1, int y1) throws Exception {
		int width = x1 - x;
		int height = y1 - y;
		IMOperation op = new IMOperation();
		op.addImage(srcPath);
		/**
		 * width：裁剪的宽度 height：裁剪的高度 x：裁剪的横坐标 y：裁剪的挫坐标
		 */
		op.crop(width, height, x, y);
		op.addImage(newPath);
		
		ConvertCmd convert = new ConvertCmd();
		String osName = System.getProperty("os.name").toLowerCase();
		if (osName.indexOf("window") != -1) {
			// linux下不要设置此值，不然会报错
			convert.setSearchPath(gmPath);
		}
		convert.run(op);
	}

	/**
	 * 根据尺寸缩放图片
	 * 
	 * @param width
	 *            缩放后的图片宽度
	 * @param height
	 *            缩放后的图片高度
	 * @param srcPath
	 *            源图片路径
	 * @param newPath
	 *            缩放后图片的路径
	 * @param type
	 *            1为大小处理，2为比例处理，如（比例：1024x1024,大小：50%x50%）
	 */
	public static String cutImage(int width, int height, String srcPath, String newPath, int type, String quality)
			throws Exception {
		IMOperation op = new IMOperation();
		ConvertCmd cmd = new ConvertCmd(true);
		op.addImage();
		String raw = "";
		if (type == 1) {
			// 按像素
			raw = width + "x" + height + "^";
		} else {
			// 按像素百分比
			raw = width + "%x" + height + "%";
		}
		op.addRawArgs("-sample", raw);
		if ((quality != null && quality.equals(""))) {
			op.addRawArgs("-quality", quality);
		}
		op.addImage();

		String osName = System.getProperty("os.name").toLowerCase();
		if (osName.indexOf("window") != -1) {
			// linux下不要设置此值，不然会报错
			cmd.setSearchPath(gmPath);
		}
		try {
			cmd.run(op, srcPath, newPath);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return newPath;
	}

	/**
	 * 给图片加水印
	 * 
	 * @param srcPath
	 *            源图片路径
	 */
	public static void addImgText(String srcPath) throws Exception {
		IMOperation op = new IMOperation();
		op.font("宋体").gravity("southeast").pointsize(18).fill("#BCBFC8").draw("text 100,100 co188.com");
		op.addImage();
		op.addImage();

		String osName = System.getProperty("os.name").toLowerCase();
		ConvertCmd cmd = new ConvertCmd(true);
		if (osName.indexOf("window") != -1) {
			// linux下不要设置此值，不然会报错
			cmd.setSearchPath("D://developsoft//GraphicsMagick-1.3.24-Q16");
		}

		try {
			cmd.run(op, srcPath, srcPath);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 图片到byte数组
	public static byte[] image2byte(String path) {
		byte[] data = null;
		FileImageInputStream input = null;
		try {
			input = new FileImageInputStream(new File(path));
			ByteArrayOutputStream output = new ByteArrayOutputStream();
			byte[] buf = new byte[1024];
			int numBytesRead = 0;
			while ((numBytesRead = input.read(buf)) != -1) {
				output.write(buf, 0, numBytesRead);
			}
			data = output.toByteArray();
			output.close();
			input.close();
		} catch (FileNotFoundException ex1) {
			ex1.printStackTrace();
		} catch (IOException ex1) {
			ex1.printStackTrace();
		}
		return data;
	}
	// byte数组到图片
	public static boolean byte2Image(byte[] data, String path) {
		if (data.length < 3 || path.equals("")){
			return false;
		}
		FileImageOutputStream imageOutput = null;
		synchronized (syncObj) {
			try {
				imageOutput = new FileImageOutputStream(new File(path));
				imageOutput.write(data, 0, data.length);
				imageOutput.close();
				
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		
		return true;
	}

	public static void main(String[] args) throws Exception {
		// cutImage("D:\\apple870.jpg", "D:\\apple870eee.jpg",98, 48, 370, 320);
		/*Long start = System.currentTimeMillis();
		 cutImage(100,100,"f:\\test\\test.png","f:\\test\\test_size.png",1,"100");
//		addImgText("e:\\37AF7D10F2D8448A9A5_bak2.jpg");
		Long end = System.currentTimeMillis();
		System.out.println("cutImage time:" + (end - start) / 3600);*/
		
		Long start = System.currentTimeMillis();
		int width=97*2;
		int height=97*2;
		String tempFileName="f:\\test\\test02.jpg";
		String fullFileName="f:\\test\\test02_middle.jpg";
		String destFileName="f:\\test\\test02_dest.jpg";
		InputStream is = new FileInputStream(tempFileName);
		// 通过文件名称读取
		BufferedImage buff = ImageIO.read(is);
		int srcWidth = buff.getWidth();// 得到图片的宽度
		int srcHeight = buff.getHeight();// 得到图片的高度
		is.close(); // 关闭Stream
		int mode=1;
		if(width>0 && height>0){	
			if(srcWidth>srcHeight){
				mode = 2;
			}else{
				mode = 1;
			}
		}else if(width>0){
			mode = 1;
		}else if(height>0){
			mode = 2;
		}
		ImageMagick imageMagick = new ImageMagick();
		imageMagick.resize(mode, tempFileName, fullFileName,destFileName, width, height, 0, 0, "100");
		Long end = System.currentTimeMillis();
		System.out.println("resize time:" + (end - start) / 3600);
	}
}
